package com.hz.winnie.demands.utils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.util.WebUtils;

public class CookieSessionUtil {
    private static Log log = LogFactory.getLog(CookieSessionUtil.class);
    /** cookie的前缀 */
    private static final String COOKIE_SESSION_NAME_PREFIX = "_scp_";

    private String COOKIE_PATH = "/";

    /** cookie域名 */
    private String cookieDomain = null;

    /** 加密类 */
    private EncryptUtil encryptUtil;

    /** 是否走https */
    private boolean cookieSecurity = false;

    /** 是否使用HttpOnly */
    private boolean httpOnly = true;

    public void setCookieDomain(String cookieDomain) {
	this.cookieDomain = cookieDomain;
    }

    public void setEncryptUtil(EncryptUtil encryptUtil) {
	this.encryptUtil = encryptUtil;
    }

    public void setCookieSecurity(boolean cookieSecurity) {
	this.cookieSecurity = cookieSecurity;
    }

    public void setHttpOnly(boolean httpOnly) {
	this.httpOnly = httpOnly;
    }

    public <T> T getObjectFromCookieSession(String name, Class<T> clazz,
	    HttpServletRequest request) {
	Cookie cookie = WebUtils.getCookie(request, COOKIE_SESSION_NAME_PREFIX
		+ name);
	if (cookie == null) {
	    return null;
	}
	try {
	    // 解密
	    return JsonUtil.fromJSON(encryptUtil.decrypt(cookie.getValue()),
		    clazz);
	} catch (Exception e) {
	    log.error("decrypt cookie based session failed: name=" + name, e);
	    return null;
	}
    }

    public void saveObjectToCookieSession(String name, Object object,
	    HttpServletResponse response) {
	// 加密
	String value;
	try {
	    value = encryptUtil.encrypt(JsonUtil.toJSON(object));
	} catch (Exception e) {
	    log.error("encrypt cookie based session failed: name=" + name
		    + ",object=" + object, e);
	    throw new RuntimeException(
		    "encrypt cookie based session failed: name=" + name
			    + ",object=" + object, e);
	}
	writeCookie(COOKIE_SESSION_NAME_PREFIX + name, value, response);
    }

    public void expireCookieSession(String name, HttpServletResponse response) {
	Cookie cookie = new Cookie(COOKIE_SESSION_NAME_PREFIX + name, "");
	if (cookieDomain != null) {
	    // 为null就写到当前完整域下
	    cookie.setDomain(cookieDomain);
	}
	cookie.setPath(COOKIE_PATH);
	cookie.setSecure(cookieSecurity);
	cookie.setMaxAge(0);
	response.addCookie(cookie);
    }

    private void writeCookie(String name, String value,
	    HttpServletResponse response) {
	if (httpOnly) {
	    String domain = "";
	    if (cookieDomain != null) {
		if (cookieDomain.startsWith(".")) {
		    domain = ";Domain=" + cookieDomain;
		} else {
		    domain = ";Domain=." + cookieDomain;
		}
	    }
	    response.addHeader("Set-Cookie", name + "=" + value + domain
		    + ";Path=" + COOKIE_PATH + ";HttpOnly");
	} else {
	    Cookie cookie = new Cookie(COOKIE_SESSION_NAME_PREFIX + name, value);
	    if (cookieDomain != null) {
		// 为null就写到当前完整域下
		cookie.setDomain(cookieDomain);
	    }
	    // 浏览器关闭后失效
	    cookie.setPath(COOKIE_PATH);
	    cookie.setMaxAge(-1);
	    cookie.setSecure(cookieSecurity);
	    response.addCookie(cookie);
	}
    }
}
